#!/usr/bin/env python

import gtk
from blend import constants
from blend import const
from mxit import handles
from mxit import errors
from blend.gui import confirmDialog
from blend.gui import addContactDialog
from blend.gui import addGroupDialog
from blend.gui import selectContactDialog
from blend.gui import editAccountWindow
from blend.gui import preferencesWindow
import gettext

gettext.install('blendIT','locale');

class signals:
   def __init__(self,blend):
      self.blend = blend;
      
   def close(self,widget,event,programSet=False):
      # Hide the buddy window only. Don't destroy it!
      if programSet == True:
         self.blend.gui.tray.displayBuddyListMenuItem.set_active(False);
      return True;

   def broadcast_message(self,widget):
      # Broadcast Message Dialog
      window = self.blend.gui.buddyWindow;
      dialog = gtk.Dialog(_("Broadcast Message"),
                          window,
                          gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                          (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                          gtk.STOCK_OK, gtk.RESPONSE_ACCEPT));

      msgEntry = gtk.Entry();
      vbox = gtk.VBox();
      vbox.pack_start(gtk.Label(_("Enter your message to broadcast to the group below:")));
      vbox.pack_end(msgEntry,True,True);
      vbox.show_all();
      dialog.vbox.pack_start(vbox);
      dialog.set_border_width(4);
      
      # Wait for a response
      response = dialog.run();
      if response == gtk.RESPONSE_ACCEPT:
         message = str(msgEntry.get_text());
         if message == "" or message == None:
            widget.destroy();
            return;

         # Get the active group
         treeselection = self.blend.gui.buddyWindow.tree.get_selection();
         (model,iter) = treeselection.get_selected();

         grp = model.get_value(iter,1).replace("<b>","").replace("</b>","");
         group = self.blend.conn.roster.get_group(grp);
         
         buddies = group._buddies.values();
         for i in range(0,len(buddies)):
            if buddies[i].presence not in (handles.Presence.OFFLINE,handles.Presence.PENDING):
               # Does a conv exist?
               display = False;
               if self.blend.gui.chatWindow.convs.getByJID(buddies[i].jid) is not None:
                  display = True; # Display it in the conv

               # Send message to this one
               self.blend.mxitmessage.sendMessage(buddies[i].jid,message,display);

         dialog.destroy();
      else:
         dialog.destroy();

   def on_buddy_drag(self,widget,context,x,y,timestamp):
      drop_info = widget.get_dest_row_at_pos(x,y);
      model = widget.get_model().get_model();

      if drop_info is None:
         path,position = (len(model)-1,), gtk.TREE_VIEW_DROP_AFTER;
      else:
         path,position = drop_info;

      treeselection = self.blend.gui.buddyWindow.tree.get_selection();
      oldIter = widget.get_model().convert_iter_to_child_iter(treeselection.get_selected()[1]);          

      iter = model.get_iter(path);
      parentIter = model.iter_parent(iter);

      if self.blend.autoAway:
         self.blend.autoAway.poke();

      if model.get_value(iter,5) is const.UNSPECIAL_GROUP:
         context.finish(False,False,timestamp);
         return True;
         
      if model.get_value(iter,5) not in (const.GROUP,const.SPECIAL_GROUP):
         # The iter selected is not a group. This means that if the parent iter
         # is none, we must fail
         if parentIter == None:
            # Fail because buddies can't be outside groups
            context.finish(False,False,timestamp);
            return True;
      
         # Also, check to see if the parent Iter is the MXit Services group
         # If it is, then we must fail because you can't add from that group
         if model.get_value(parentIter,5) == const.UNSPECIAL_GROUP:
            # Fail. Since we can't add to the list!
            #print "Can't move to MXit Services!";
            context.finish(False,False,timestamp);
            return False;
      else:
         parentIter = iter;

      # Check to see if we are trying to move something that isn't
      # allowed to be moved.
      if model.get_value(oldIter,5) in (const.SPECIAL_GROUP,
                                        const.UNSPECIAL_GROUP,
                                        const.GROUP,
                                        const.INVITE,
                                        const.FILESERVICE,
                                        const.SERVICE):
         # Fail
         context.finish(False,False,timestamp);
         return True;
      else:
         # Find the iter it must get to
         newIter = model.append(parentIter);

         # Copy the data
         for i in range(0,7):
            value = model.get_value(oldIter,i);
            model.set_value(newIter,i,value);        

         # Now we must send a buddy update
         if model.get_value(newIter,5) == const.BUDDY:
            buddy = self.blend.conn.roster.get_buddy(model.get_value(newIter,6));
            grp = model.get_value(parentIter,1).replace("<b>","").replace("</b>","");

            group = self.blend.conn.roster.get_group(grp);
            if group != buddy.group:
               self.blend.conn.update_buddy(buddy,group=group);
         
         context.finish(True,True,timestamp);
      return True;


   def on_edit_account(self,widget):
      tree = self.blend.gui.buddyWindow.tree;
      treeselection = tree.get_selection();
      (model,path) = treeselection.get_selected_rows();
      widget.set_cursor(path[0],tree.get_column(1),True)
      tree.grab_focus();

   def on_logoff(self,widget,logoff):
      if self.blend.currentlyConnected:
         # log off
         self.blend.logoff();
      else:
         # log on
         self.blend.login();

   def on_edit_own_account(self,widget):
      # Laucn the edit account window
      if self.blend.currentlyConnected:
         self.blend.gui.editAccountWindow = editAccountWindow.editAccountWindow(self.blend);
         self.blend.gui.editAccountWindow.show();
      else:
         self.blend.gui.createErrorMessage(self.blend.gui.buddyWindow,
                                           _("You must be online to edit your account."));

   def on_add_contact(self,widget,getGroup=False):
      if getGroup == True:
         # Check what group is selected.
         treeselection = self.blend.gui.buddyWindow.tree.get_selection();
         (model,iter) = treeselection.get_selected();
         group = model.get_value(iter,1).replace("<b>","").replace("</b>","");
      else:
         group = None;
      window = self.blend.gui.buddyWindow;
      dialog = addContactDialog.addContactDialog(self.blend,window,group);
      dialog.run();
      
   def on_create_group(self,widget):
      window = self.blend.gui.buddyWindow;
      dialog = addGroupDialog.addGroupDialog(self.blend,window);
      dialog.run();

   def on_hide_contacts(self,widget):
      if widget.get_active():
         # Engage the filter!
         self.blend.config.hideOfflineContacts = True;
         self.blend.gui.buddyWindow.model.refilter();
      else:
         # Disenage the filter!
         self.blend.config.hideOfflineContacts = False;
         self.blend.gui.buddyWindow.model.refilter();
      
   def on_preferences(self,*params):
      self.blend.gui.preferencesWindow = preferencesWindow.preferencesWindow(self.blend);
      self.blend.gui.preferencesWindow.draw();

   def on_debug_console(self,widget):
      n = self.blend.gui.chatWindow.convs.getPageNumberFromJID('debug@__Blendit');
      if n is None:
         # Create tab
         bud = handles.Buddy('debug@__Blendit','Debug',
                             '',handles.BuddyType.DEBUG);
         self.blend.gui.chatWindow.createNewChat(bud,True,self.blend.gui.chatWindow.drawDebugPage);
      else:
         # Jump to tab
         self.chatWindow.notebook.set_current_page(n);

   def accept_invite(self,widget):
      treeselection = self.blend.gui.buddyWindow.tree.get_selection();
      #print treeselection, str(treeselection);
      (model,iter) = treeselection.get_selected();
      buddy = self.blend.conn.roster.get_buddy(model.get_value(iter,6));
      self.blend.conn.accept_invite(buddy);

   def reject_invite(self,widget):
      treeselection = self.blend.gui.buddyWindow.tree.get_selection();
      (model,iter) = treeselection.get_selected();
      buddy = self.blend.conn.roster.get_buddy(model.get_value(iter,6));
      self.blend.conn.reject_invite(buddy);
      iter = model.convert_iter_to_child_iter(iter);
      model.get_model().remove(iter);

   def on_rightclick_send_message(self,widget,iter=None):
      treeselection = self.blend.gui.buddyWindow.tree.get_selection();
      (model,iter) = treeselection.get_selected();
      jid = model.get_value(iter,6);
      buddy = self.blend.conn.roster.get_buddy(jid);
      # There is a bug here. Fix it.
      # Doesn't do type checking... oh, wait.. does it need to?
      # Check that.
      # ^-- Please tell me WTF I meant here O.o (05/06/09)
      self.blend.gui.chatWindow.createNewChat(buddy,True);
      if self.blend.autoAway:
         self.blend.autoAway.poke();

   def on_rightclick_inviteMMx(self,widget):
      # Popup the MMix dialog but change it slightly.
      dialog = selectContactDialog.selectContactDialog(self.blend,_("Invite to MultiMx"));
      response = dialog.run();
      if response == gtk.RESPONSE_ACCEPT:
         buddies = dialog.getSelectedContacts();
         #print "yay", buddies;
         treeselection = self.blend.gui.buddyWindow.tree.get_selection();
         (model,iter) = treeselection.get_selected();
         jid = model.get_value(iter,6);
         room = self.blend.conn.roster.get_room(jid);
         self.blend.conn.invite_buddies_room(room,buddies);
      dialog.destroy();
   
   def on_rightclick_closeMMx(self,widget):
      treeselection = self.blend.gui.buddyWindow.tree.get_selection();
      (model,iter) = treeselection.get_selected();
      jid = model.get_value(iter,6);
      n = self.blend.gui.chatWindow.convs.getPageNumberFromJID(jid);
      if n is not None:
         self.blend.gui.chatWindow.destroyChat(n);

   def on_reinvite_contact(self,widget):
      treeselection = self.blend.gui.buddyWindow.tree.get_selection();
      (model,iter) = treeselection.get_selected();
      jid = model.get_value(iter,6);
      buddy = self.blend.conn.roster.get_buddy(model.get_value(iter,6));
      group = buddy.group;
      alias = model.get_value(iter,1);
      
      # Only reinvite contact if they're not online...
      if buddy.isOnline():
         return False;
      else:
         self.blend.conn.invite(jid,alias,group);

   def on_remove_contact(self,widget):
      treeselection = self.blend.gui.buddyWindow.tree.get_selection();
      (model,iter) = treeselection.get_selected();
      jid = model.get_value(iter,6);
      buddyName = model.get_value(iter,1);
      msg = _("Are you sure you want to remove %s from your contacts?");
      msg = msg % buddyName;
      window = self.blend.gui.buddyWindow;
      dialog = confirmDialog.confirmDialog(msg,window);
      dialog.connect('response',self.confirm_remove_contact,jid);
      dialog.run();

   def confirm_remove_contact(self,widget,response,jid):
      if response == gtk.RESPONSE_YES:
         buddy = self.blend.conn.roster.get_buddy(jid);
         self.blend.conn.remove_buddy(buddy);
         widget.destroy();
      else:
         widget.destroy();

   def block_contact(self,widget):
      treeselection = self.blend.gui.buddyWindow.tree.get_selection();
      (model,iter) = treeselection.get_selected();
      jid = model.get_value(iter,6);
      name = model.get_value(iter,1);
      msg = _("Are you sure you want to block %(name)s (%(id)s)?") % {'name': name, 'id': jid};
      window = self.blend.gui.buddyWindow;
      dialog = confirmDialog.confirmDialog(msg,window);
      dialog.connect('response',self.confirm_block_contact,jid);
      dialog.run();

   def confirm_block_contact(self,widget,response,jid):
      if response == gtk.RESPONSE_YES:
         buddy = self.blend.conn.roster.get_buddy(jid);
         self.blend.conn.block_contact(buddy);
         # Block contact
         iter = self.blend.gui.buddyWindow.findBuddy(buddy);
         if iter != None:
            #iter = model.convert_iter_to_child_iter(iter);
            self.blend.gui.buddyWindow.model.get_model().remove(iter);
         widget.destroy();
      else:
         widget.destroy();

   # Get the mood that the user has selected and
   # send it to control for it to be changed
   def on_moodBox_change(self,widget):
      model = widget.get_model();
      iter = widget.get_active_iter();
      mood = constants.C.moods[handles.Mood.byid(model.get_value(iter,2))];
      self.blend.conn.set_mood(mood.const);
      self.blend.gui.tray.changeMood(mood);

   # Get the status that the user has selected and
   # send it to control for it to be changed      
   def on_statusBox_change(self,widget):
      
      model = widget.get_model();
      iter = widget.get_active_iter();
      if iter is None:
         #print 'No iter', widget.get_active();
         return;

      try:
         status = constants.C.presences[handles.Presence.byid(model.get_value(iter,2))];
         if status.const == handles.Presence.OFFLINE:
            if self.blend.currentlyConnected:
               # Log off
               self.blend.logoff();
            return;

         if self.blend.currentlyConnected:
            self.blend.conn.set_presence(status.const);
            self.blend.gui.tray.changePresence(status);
         else:
            self.blend.login();
      except KeyError:
         #print "failed on", model.get_value(iter,1), model.get_value(iter,2), "probably temp status";
         pass;

   # We want right clicks to have a context menu
   def on_buddyList_press_event(self,widget,event):
      if self.blend.autoAway:
         self.blend.autoAway.poke();

      # Double Click
      if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
         # Fire up the chatWindow (if it's not fired up already) and make a tab!
         # Only if it's the correct type.. of course
         treeselection = widget.get_selection();
         (model,iter) = treeselection.get_selected();
         if iter == None:
            return;
         type = model.get_value(iter,5);
         if type in (const.UNSPECIAL_GROUP,const.SPECIAL_GROUP,const.GROUP):
            # Expand/Unexpand
            path = treeselection.get_selected_rows()[1][0];
            if widget.row_expanded(path):
               widget.collapse_row(path);
            else:
               widget.expand_row(path,False);
         elif type == const.MULTIMX:
            # Multimx window
            # This will just focus on the MultiMx
            jid = model.get_value(iter,6);
            n = self.blend.gui.chatWindow.convs.getPageNumberFromJID(jid);
            if n is not None:
               self.blend.gui.chatWindow.notebook.set_current_page(n);
         elif type == const.FILESERVICE:
            # Gallery window
            # For now, it will be the same as a usual chat window
            # until a later release.
            jid = model.get_value(iter,6);
            buddy = self.blend.conn.roster.get_buddy(jid);
            self.blend.gui.chatWindow.createNewChat(buddy,True);
         elif type == const.INVITE:
            # Cause the right click menu to show
            x = int(event.x);
            y = int(event.y);
            time = event.time;
            pathData = widget.get_path_at_pos(x,y);
            if pathData != None:
               path,col,cellx,celly = pathData;
               widget.grab_focus();
               widget.set_cursor(path,col,0);
               self.blend.gui.buddyWindow.displayTreePopupMenu(path,col,event.button,
                                                               time);
         else:
            jid = model.get_value(iter,6);
            buddy = self.blend.conn.roster.get_buddy(jid);
            self.blend.gui.chatWindow.createNewChat(buddy,True);
         
      # Right Click
      elif event.button == 3:
         x = int(event.x);
         y = int(event.y);
         time = event.time;
         pathData = widget.get_path_at_pos(x,y);

         if pathData != None:
            path,col,cellx,celly = pathData;
            widget.grab_focus();
            widget.set_cursor(path,col,0);
            self.blend.gui.buddyWindow.displayTreePopupMenu(path,col,event.button,
                                                      time);

   def on_buddyList_edited(self,widget,path,text):
      # Retrieve the buddy's data from the treeview ((s)he will be the selected one)
      treeselection = self.blend.gui.buddyWindow.tree.get_selection();
      (model,iter) = treeselection.get_selected();
      iter = model.convert_iter_to_child_iter(iter);
      model = model.get_model();
      name = model.get_value(iter,1);
      jid = model.get_value(iter,6);
      type = model.get_value(iter,5);
      text = text.strip();
      
      if type == const.BUDDY:
         if text != name.replace("<b>","").replace("</b>",""):
            buddy = self.blend.conn.roster.get_buddy(jid);
            try:
               self.blend.conn.update_buddy(buddy,name=text);
               model.set_value(iter,1,text);
            except errors.MxitException:
               # Error, buddy name taken already
               self.blend.gui.createErrorMessage(self.blend.gui.buddyWindow,
                                                 _("A contact with that alias already exists."));
      elif type == const.GROUP:
         # Not allowed to change the name to BlendIT or MXit Services
         if text == "BlendIT":
            model.set_value(iter,1,name);
         if text == "MXit Services":
            model.set_value(iter,1,name);
           

         if text != name.replace("<b>","").replace("</b>",""):
            # Update group name
            model.set_value(iter,1,"<b>%s</b>" % text);
            result = self.blend.conn.update_group(name.replace("<b>","").replace("</b>",""),text);
            #print result;
            if result is False:
               model.set_value(iter,1,name);
               # Error, group name already taken
               self.blend.gui.createErrorMessage(self.blend.gui.buddyWindow,
                                                 _("A group with that name already exists."));
         else:
            #print 'same name!';
            pass;
      else:
         #print 'lol, failzor';
         pass;